//
// Created by PC on 2023/9/28.
/*
 * 2019 年海淀区中小学生信息学奥林匹克竞赛
 * 试题 4：异构单词（共 10 个测试点，每个点 10 分）
 OJ: https://www.luogu.com.cn/problem/T101404

【问题描述】
在一些英文单词中有些单词相互之间是“异构”的，比如：meat、mate、tame、team
等，即组成他们的字母以及字母数量完全一样，只有字母出现的顺序不一样（seen 和 sen
不满足相互异构的条件）。现在给你 N 个单词，每个单词由 4 个小写英文字母组成，请找出有多少对单词满足异构条件。注意，相同单词不会重复出现且<si,sj>算一对。
【输入说明】
第一行为一个正整数 n，表示单词数量。
以下 n 行每行包含一个满足题目要求的单词。
【输出说明】
输出一个数，表示异构单词对的数量。
【样例输入】
4
meat
mate
tame
team
【样例输出】
6
【数据范围】
对 30%数据，有 2≤n≤100；
对 100%数据，有 2≤n≤10^5
 * */
//只得20分
//


#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int n, ret = 0;
    cin >> n;
    vector<string> v;
    for (int i = 0; i < n; ++i)
    {
        string s, ss;
        int arr[26] = {0};
        cin >> s;
        // 入桶
        for (int j = 0; j < 4; ++j)
        {
//            sum+=(s[j]-'a');
            arr[s[j] - 'a']++;
        }
        ss = "";
        // 桶排序 将每个单词按照字典序排列, 如果是异构的那么排序后都是一样的单词
        for (int k = 0; k < 26; ++k)
        {
            if (arr[k] > 0)
                for (int j = 0; j < arr[k]; ++j)
                {
                    ss += char(k + 'a');
                }
        }
        v.push_back(ss);
//        cout<<ss<<endl;
    }
    // 计算有多少组m相同的字符串, 每组有多少个count,建立m长度的数组,数组的元素就是每组的count数
    // 从第一个元素开始往后找, 有相同的就count++然后将其变成"", 直到结束, 再重头找, 直到所有都是""
//    vector<int> group;
    int group[10000] = {0};
    int index = 0, count = 0, empty_count = 0; //index:索引,count保存索引中的元素,empty_count为""的个数
    for (int l = 0; l < v.size(); ++l)
    {
        count = 0;
        if (v[l] != "")
        {
            string cur = v[l];
            v[l] = "";
            ++empty_count;
            ++count;
            for (int i = l; i < v.size(); ++i)
            {
                if (v[i] == cur)
                {
                    v[i] = "";
                    ++count;
                    ++empty_count;
                }
            }
            group[index] = count;
            ++index;
//            group.push_back(count);
        }
        // 当空字符串数量和总数相等得时候就可以退出了
        if (empty_count == v.size())
            break;
    }
    // 计算有多少对"异构"的单词,(n-1)!
    for (int m = 0; m < 10000; ++m)
    {
        if (group[m] > 1)
        {
            printf("%d,%d\n", m, group[m]);
            int pairs=1;
            for (int i = 1; i < group[m]; ++i)
            {
                pairs*=i;
            }
            ret+=pairs;
        }
    }
    cout<<ret;
    return 0;
}
